iT邦幫忙

2021 iThome 鐵人賽

DAY 11
1
Mobile Development

如何用下班時間開發App經營副業系列 第 11

在 React Native 裡實作 NSFW (Not suitable for work,工作場合不宜) 分類器

  • 分享至 

  • xImage
  •  

需求與場景

雖然我們的 App 為了怕麻煩,有要求 18+ 以上才能使用,但還是怕會有繞過這個限制的小孩
在一對一聊天的場景,可以傳圖片。雖然大部分都非常健全,但偶爾還是會出現色情圖片。
為了怕發生什麼對我們平台麻煩的事,我們決定要自動偵測是不是裸照,在搭配他們自己說的年齡(不等於實際年齡),如果有可能有十八歲以下,我們會自動跳出一個警告說如果有發現任何不法事宜會配合警察。

第一步:尋找分類器模型

完成我們的需求的第一步,就是要有一個裸照分類器。這個應該是非常常見的需求,所有的用戶產生內容平台應該都有。我們一定沒必要自己做,而且自己做也不一定做得比別人好。所以我們就很自然的去 GitHub 上找已經訓練好的模型。
Github 上只要搜 "NSFW" (Not suitable for work,工作場合不宜) 就有非常多適合各種語言的現成模型。比如說
infinitered/nsfwjs: NSFW detection on the client-side via TensorFlow.js (github.com)
或是
GantMan/nsfw_model: Keras model of NSFW detector (github.com)

評估模型

我們找了幾個 javascript 可以用的,做了簡單的評估。
評估用的資料集是 1200 張實際用戶傳的圖片,一半 positive(有裸露),一半 negative(正常)。
然後就簡單的測了一下 precision 跟 recall。
最後選了一個表現最佳的模型。

實作

取的模型後,下一步是要加進 code 做實時判斷。
因為我們用是 tensorflow 的模型,我們就用了 tfjs 這個 library
https://www.npmjs.com/package/@tensorflow/tfjs

import '@tensorflow/tfjs';
import * as tfnode from '@tensorflow/tfjs-node';

核心部分的實作如下

tfnode.tidy(() => {
	const tensor = tfnode.node.decodeImage(file.buffer, 3, 'int32');
	const image = tfnode.image
	.resizeBilinear(tensor, [IMAGE_SIZE, IMAGE_SIZE])
	.mul(1.0 / 255.0)
	.reshape([1, IMAGE_SIZE, IMAGE_SIZE, 3]);
	const predictions = mobilenet.predict(image) as tfnode.Tensor;
	const predictedData = predictions.dataSync();
	const adultRatio = predictedData[3] + predictedData[4];
	resolve(adultRatio);
});

效能影響

因為傳圖片不是主要功能,頻率也不高,加了這個判斷,對效能的影響不大。
唯一一種情況我們有優化的是,我們發現有些人會一直傳同一張圖片,為了避免每次都重複判斷,判斷過的圖過我們會轉成 hash,把 hash 跟結果存在 DB 裡。如果以前有判斷過,就直接取用。

結論

在做這個功能之前,曾經被抱怨過一兩次,但自從加了這個分類器跟警告之後,一年多來都沒有出現任何問題,所以我覺得這個功能有達到我們預期的效果了!

最新文章會分享在臉書:https://www.facebook.com/gigi.wuwu/
歡迎留言討論


上一篇
React Native 的動畫好幫手:Lottie
下一篇
增加 App 下載量必備的 ASO 工具
系列文
如何用下班時間開發App經營副業30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言